package cn.itcast.n4.exercise;

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Vector;

/**
 * className: ExerciseSell
 * description:
 * date: 2023/2/13 0013-PM 8:15:43
 * <p>
 * project: concurrent
 * package: cn.itcast.n4.exercise
 * email: 1085844536@qq.com
 * version:
 *
 * @author WangGuojian
 */
@Slf4j(topic = "c.ExerciseSell")
public class ExerciseSell {

    public static void main(String[] args) throws InterruptedException {
        // 模拟多人买票
        TicketWindow window = new TicketWindow(10000);

        // 所有线程的集合
        List<Thread> threadList = new ArrayList<>();
        // 卖出的票数统计
        List<Integer> amountList = new Vector<>();
        for (int i = 0; i < 2000; i++) {
            Thread thread = new Thread(() -> {
                //  买票
                int amount = window.sell(random(5));
                // 统计买票数
                amountList.add(amount);
            });
            threadList.add(thread);
            thread.start();
        }

        for (Thread thread : threadList) {
            thread.join();
        }

        log.debug("余票:{}", window.getCount());
        log.debug("卖出的票数:{}", amountList.stream().mapToInt(i -> i).sum());
    }

    /**
     * Random 为线程安全
     */
    static Random random = new Random();

    /**
     * 随机 1~5
     *
     * @return {@link Integer} 获取随机数
     */
    public static int random(int amount) {
        return random.nextInt(amount) + 1;
    }
}

/**
 * 售票窗口
 */
class TicketWindow {
    private int count;
    ;

    public TicketWindow(int count) {
        this.count = count;
    }

    /**
     * 获取余票数量
     *
     * @return {@link Integer} 余票数量
     */
    public int getCount() {
        return count;
    }

    /**
     * 售票
     *
     * @param amount {@link Integer} 数量
     * @return {@link Integer} 数量
     */
    public synchronized int sell(int amount) {
        if (this.count >= amount) {
            this.count -= amount;
            return amount;
        }
        return 0;
    }
}